# encoding: UTF-8
'''
Created: 2014-05-02 08:21

@author: VAN
'''
'''
Python通过两个标准库thread和threading提供对线程的支持。
thread提供了低级别的、原始的线程以及一个简单锁（原语锁）,不支持守护线程，主线程退出，所有线程都强制退出
threading基于Java的线程模型设计,提供更高级别，功能更强的线程管理
'''

import Queue
import thread
from threading import Thread   
import threading
import time
import urllib2


def func():
    print 'func'

def thread_run(lock):
    print lock.locked
    if lock.acquire():
        try:
            print lock.locked
            time.sleep(5)
        finally:
            lock.release()
    thread.exit_thread()

def thread_demo():
    lock = thread.allocate_lock()
    thread.start_new_thread(thread_run, (lock))
    
def threading_run(lock):
    if lock.acquire():
        try:
            print 'acquired'
        finally:
            lock.release()
    print "threading"
 
class ThreadingClazz(threading.Thread):
    def run(self):
        print 'ThreadDemo run'

def produce(condition, product):
    if condition.acquire():
        while True:
            if product is None:
                print 'produce...'
                product = 'produce'
                condition.notify()
            condition.wait()
            time.sleep(2)
        condition.release()
            
def consume(condition, product):
    if condition.acquire():
        while True:
            if product is not None:
                print 'consume...'
                product = None
                condition.notify()
            condition.wait()
            time.sleep(2)
        condition.release()
            
def semaphore_run(semaphore):
    if semaphore.acquire():
        try:
            print 'semaphore'
        finally:
            semaphore.release()
            
def evt_run(evt):
    evt.wait()
    print 'evt'
              
def threading_demo():
    lock = threading.Lock()
    t1 = threading.Thread(target=threading_run, args=(lock))
    t2 = threading.Thread(target=threading_run, args=(lock))
    t3 = threading.Thread(target=threading_run, args=(lock))
    t1.start()
    t2.start()
    t3.start()
    
    t = ThreadingClazz()
    t.start()
    
    '''
    Condition（条件变量）通常与一个锁关联。需要在多个Contidion中共享一个锁时，可以传递一个Lock/RLock实例给构造方法，否则它将自己生成一个RLock实例
    Condition 不仅有Lock的锁定池外，还有一个等待池，等待池中的线程处于状态图中的等待阻塞状态，直到另一个线程调用notify()/notifyAll()通知；得到通知后线程进入锁定池等待锁定
    '''
    condition = threading.Condition()
    product = None
 
    t1 = threading.Thread(target=produce, args=(product, condition))
    t2 = threading.Thread(target=consume, args=(product, condition))
    t2.start()
    t1.start()
    
    '''
    Semaphore管理一个内置的计数器，每当调用acquire()时-1，调用release() 时+1。计数器不能小于0；当计数器为0时，acquire()将阻塞线程至同步锁定状态，直到其他线程调用release()
    BoundedSemaphore 与Semaphore的唯一区别在于前者将在调用release()时检查计数器的值是否超过了计数器的初始值，如果超过了将抛出一个异常
    '''
    semaphore = threading.Semaphore(5)
    t1 = threading.Thread(target=semaphore_run, args=(semaphore))
    t2 = threading.Thread(target=semaphore_run, args=(semaphore))
    t2.start()
    t1.start()
    
    '''
    Event（事件）是最简单的线程通信机制之一：一个线程通知事件，其他线程等待事件。Event内置了一个初始为False的标志，当调用set()时设为True，调用clear()时重置为 False。
    Event其实就是一个简化版的 Condition。Event没有锁，无法使线程进入同步阻塞状态，wait()将阻塞线程至等待阻塞状态。。
    '''
    evt = threading.Event()
    t1 = threading.Thread(target=evt_run, args=(evt))
    t2 = threading.Thread(target=evt_run, args=(evt))
    t2.start()
    t1.start()
    evt.set()  # notify,the function like barrier
    
    '''
    threading.Timer(5, func) #Timer（定时器）是Thread的派生类，用于在指定时间后调用一个方法
    threading.local() #一个“线程-属性字典”的字典，管理 thread-local（线程局部的）数据 
    '''
    
class Worker(Thread):
    worker_count = 0;
    def __init__(self, workQueue, resultQueue, timeout=5, **kwargs):
        Thread.__init__(self, **kwargs)
        self.id = Worker.worker_count
        Worker.worker_count += 1
        self.setDaemon(True)
        self.workQueue = workQueue
        self.resultQueue = resultQueue
        self.timeout = timeout
        self.start()
    
    def run(self):
        while 1:
            try:
                (func, args, kwargs) = self.workQueue.get(timeout=self.timeout)
                res = func(*args, **kwargs)
                print "worker[%2d]: %s" % (self.id, str(res))
                self.resultQueue.put(res)
            except Queue.Empty:
                break;
            except :
                print 'error run'


class WorkerManager:
    def __init__(self, number_of_workers=10, timeout=5):
        self.workQueue = Queue.Queue()
        self.resultQueue = Queue.Queue()
        self.workers = []
        self.timeout = timeout
        self._recruitThreads(number_of_workers)
        
    def _recruitThreads(self, number_of_workers):
        for i in range(number_of_workers):
            worker = Worker(self.workQueue, self.resultQueue, self.timeout)
            self.workers.append(worker)
            
            
    def wait_for_complete(self):
        while len(self.workers):
            worker = self.workers.pop()
            worker.join()
            if worker.isAlive() and not self.workQueue.empty():
                self.worker.append(worker)
            
    def add_work(self, func, *args, **kwargs):
        self.workQueue.put((func, args, kwargs))
    def get_result(self, *args, **kwargs):
        return self.resultQueue.get(*args, **kwargs)
    

def worker_func(*args, **kwargs):
    try:   
        urllib2.urlopen('http://www.baidu.com/').read()   
    except:   
        print 'error'  
        
    return time.asctime()


# controller = WorkerManager(10)
# for i in range(100):
#     controller.add_work(worker_func)
#    
# controller.wait_for_complete()
print '++++++++++++++++++'
    


    
    

    
    
    



